import { instantiate, Node, Prefab, SafeArea, Widget } from "cc"
import { UICallbacks, ViewParams } from "./Defines";
import { UIConfig } from "./LayerManager";
import { hiyooo } from "../../HiYOOO";
import { DelegateComponent } from "./DelegateComponent";
export class LayerUI extends Node{
    /**窗口打开失败事件*/
    onOPenFailuer:Function = null!;

    //显示界面的节点集合
    protected ui_nodes = new Map<string,ViewParams>();
    //移除界面的缓存数据
    protected ui_cache = new Map<string,ViewParams>();
    /**
     * UI界面基础层，允许添加多个预制节点
     * @param name 界面层的名称 
    */
    constructor(name:string){
        super(name);
        //添加Widget对齐组件
        const widget:Widget = this.addComponent(Widget);
        widget.isAlignLeft = widget.isAlignLeft = widget.isAlignRight = widget.isAlignTop = widget.isAlignBottom = true;
        widget.left = widget.right = widget.top=widget.bottom = 0;
        widget.alignMode = 2;
        widget.enabled = true;
    }

    public add (config:UIConfig,params:any,callbacks:UICallbacks):void{
        if (this.ui_nodes.has(config.prefab)) {
            console.warn(`路径为【${config.prefab}】的预制重复加载`)
            return;
        }
        let vp  = this.ui_cache.get(config.prefab);
        if (vp == null) {
            vp  = new ViewParams();
            vp.config = config;
        }
        this.ui_cache.set(config.prefab,vp);
        vp.params = params ?? {}
        vp.callback = callbacks ?? {}
        vp.valid = true;

        this.load(vp,config.bundle);
    }

    /**
     * 
     * @param vp 页面参数
     * @param bundle 
     */
    protected async load(vp:ViewParams,bundle?:string){
        //加载等待界面
        const timerId  = setTimeout(this.onLoadingTimeoutGui,hiyooo.config.game.loadingTimeoutGui);

        if (vp && vp.node) { 
            await this.showUI(vp);
        }else{
            //指定bundle，如果bundle 不存在的话，则使用默认的resources
            bundle = bundle || hiyooo.res.defaultBundleName;
            const res  = await hiyooo.res.loadAsync(bundle,vp.config.prefab,Prefab);
            if (res) {
                vp.node = instantiate(res)
                if (vp.config.safeArea) {
                    vp.node.addComponent(SafeArea)
                }
                const dc = vp.node.addComponent(DelegateComponent)
                dc.vp = vp;
                dc.onCloseWindow = this.onCloseWindow.bind(this);
                
                await this.showUI(vp)
            }else{
                console.warn(`路径为【${vp.config.prefab}】的预制加载失败`)
                this.failure(vp)
            }
             

        }


        hiyooo.gui.waitClose();
        clearTimeout(timerId);
    }

    /**
     * 显示超时显示的GUI
     */
    private onLoadingTimeoutGui(){
        hiyooo.gui.waitOpen();
    }

    /**
     * 显示界面
     * @param vp 
     * @returns bool
     */
    protected async showUI(vp:ViewParams):Promise<boolean>{
        const comp  = vp.node.getComponent(DelegateComponent);
        const r:boolean  = await comp.add();
        if (r) {
            vp.node.parent = this;
            //标记界面的可用状态
            vp.valid = true;
        }else{
            this.failure(vp)
        }
        return r;

    }

    /**
     * 关闭窗口
     * @param vp 窗口参数
     */
    protected onCloseWindow(vp:ViewParams){
        this.ui_cache.delete(vp.config.prefab)
    }

    protected failure(vp:ViewParams){
        this.onCloseWindow(vp);
        vp.callback && vp.callback.onLoadFailure && vp.callback.onLoadFailure();
        this.onOPenFailuer && this.onOPenFailuer();
    }


    /**
     * 删除Layer
     * @param prefabPath prefab 路径
     * @param isDestroy 是否删除后释放
     */
    public remove(prefabPath:string,isDestroy?:boolean):void{
        //标识是否释放，首先设置为undefine 避免会被设置成其它值 
        let release  = undefined;
        //如果没有已经传过来 isDestroy ，则把release 标识设置为isDestroy
        if (isDestroy !== undefined) {
            release = isDestroy;
        }
        //查看界面是否在界面集合中
        const vp  = this.ui_nodes.get(prefabPath)
        if (vp) {
            if (release === undefined) {
                // 优先使用参数中控制的释放条件，如果未传递参数则用配置中的释放条件，默认不缓存关闭的界面
                release = vp.config.destroy!==undefined ? vp.config.destroy : true;
            }
            if (release === false) {
                //如果传false，则把界面缓存起来，下次再使用。
                this.ui_cache.set(prefabPath,vp)
            }
            const comp =  vp.node.getComponent(DelegateComponent)!;
            comp.remove(release)

        }
        //确保删除后缓存界面的资源
        if (release  === true) {
            this.removeCache(prefabPath)
        }
    }

    private removeCache(prefabPath:string){
        const vp = this.ui_cache.get(prefabPath)
        if(vp){
            this.onCloseWindow(vp);
            this.ui_cache.delete(prefabPath)
            const childNode = vp.node;
            childNode.destroy();
        }
    }

    public clear(isDestroy:boolean):void{
        //清除所有界面
        this.ui_nodes.forEach((value:ViewParams,key:string) =>{
            this.remove(value.config.prefab,isDestroy)
            value.valid = false;
        })
        //清除Map 中的所有数据
        this.ui_nodes.clear();
        //清除所有缓存数据
        if (isDestroy) {
            this.ui_cache.forEach((value:ViewParams,prefabPath:string)=>{
                this.removeCache(prefabPath);
            })
        }

    }

    /**
     * 当前层是否包含指定界面
     * @param prefabPath 预制体的路径
     * @returns boolearn
     */
    public has(prefabPath:string):boolean{
        return this.ui_nodes.has(prefabPath)
    }
    
    /**
     * 根据路径获取指定已经打打开的界面
     * @param prefab 
     * @returns Node
     */
    public get(prefab:string):Node{
        const vp = this.ui_nodes.get(prefab);
        if (vp) {
            return vp.node;
        }
        return null!;
    }

    


}